package com.immediatus.engine.collision;

public class ShapeCollisionChecker extends BaseCollisionChecker{

    public static final int VERTEX_INDEX_X = 0;
    public static final int VERTEX_INDEX_Y = 1;

    public static boolean checkCollision(final int verticesALength_, final float[] verticesA_, final int verticesBLength_, final float[] verticesB_){
        for (int a = verticesALength_ - 4; a >= 0; a -= 2){
            if (ShapeCollisionChecker.checkCollisionSub(a, a + 2, verticesA_, verticesB_, verticesBLength_)){
                return true;
            }
        }
        if (ShapeCollisionChecker.checkCollisionSub(verticesALength_ - 2, 0, verticesA_, verticesB_, verticesBLength_)){
            return true;
        } else{
            if (ShapeCollisionChecker.checkContains(verticesA_, verticesALength_, verticesB_[VERTEX_INDEX_X], verticesB_[VERTEX_INDEX_Y])){
                return true;
            } else if (ShapeCollisionChecker.checkContains(verticesB_, verticesBLength_, verticesA_[VERTEX_INDEX_X], verticesA_[VERTEX_INDEX_Y])){
                return true;
            } else{
                return false;
            }
        }
    }

    private static boolean checkCollisionSub(final int vertexIndexA1_, final int vertexIndexA2_, final float[] verticesA_, final float[] verticesB_, final int verticesBLength_){
        final float vertexA1X = verticesA_[vertexIndexA1_ + VERTEX_INDEX_X];
        final float vertexA1Y = verticesA_[vertexIndexA1_ + VERTEX_INDEX_Y];
        final float vertexA2X = verticesA_[vertexIndexA2_ + VERTEX_INDEX_X];
        final float vertexA2Y = verticesA_[vertexIndexA2_ + VERTEX_INDEX_Y];

        for (int b = verticesBLength_ - 4; b >= 0; b -= 2){
            if (LineCollisionChecker.checkLineCollision(vertexA1X, vertexA1Y, vertexA2X, vertexA2Y,
                    verticesB_[b + VERTEX_INDEX_X],
                    verticesB_[b + VERTEX_INDEX_Y],
                    verticesB_[b + 2 + VERTEX_INDEX_X],
                    verticesB_[b + 2 + VERTEX_INDEX_Y])) return true;
        }

        return LineCollisionChecker.checkLineCollision(vertexA1X, vertexA1Y, vertexA2X, vertexA2Y,
                verticesB_[verticesBLength_ - 2],
                verticesB_[verticesBLength_ - 1],
                verticesB_[VERTEX_INDEX_X],
                verticesB_[VERTEX_INDEX_Y]);
    }

    public static boolean checkContains(final float[] vertices_, final int verticesLength_, final float x_, final float y_){
        int edgeResultSum = 0;

        for (int i = verticesLength_ - 4; i >= 0; i -= 2){
            final int edgeResult = BaseCollisionChecker.relativeCCW(vertices_[i], vertices_[i + 1], vertices_[i +
                    2], vertices_[i + 3], x_, y_);
            if (edgeResult == 0){
                return true;
            } else{
                edgeResultSum += edgeResult;
            }
        }
        final int edgeResult = BaseCollisionChecker.relativeCCW(vertices_[verticesLength_ - 2], vertices_[
                verticesLength_ - 1], vertices_[VERTEX_INDEX_X], vertices_[VERTEX_INDEX_Y], x_, y_);
        if (edgeResult == 0){
            return true;
        } else{
            edgeResultSum += edgeResult;
        }

        final int vertexCount = verticesLength_ / 2;
        return edgeResultSum == vertexCount || edgeResultSum == -vertexCount;
    }
}
